home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / lightning-0.8-tb-win.xpi / components / calItipEmailTransport.js < prev    next >
Text File  |  2008-03-04  |  18KB  |  442 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Simdesk Technologies code.
  15.  *
  16.  * The Initial Developer of the Original Code is
  17.  * Simdesk Technologies.
  18.  * Portions created by the Initial Developer are Copyright (C) 2007
  19.  * the Initial Developer. All Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *   Clint Talbert <ctalbert.moz@gmail.com>
  23.  *   Matthew Willis <lilmatt@mozilla.com>
  24.  *
  25.  * Alternatively, the contents of this file may be used under the terms of
  26.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  27.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28.  * in which case the provisions of the GPL or the LGPL are applicable instead
  29.  * of those above. If you wish to allow use of your version of this file only
  30.  * under the terms of either the GPL or the LGPL, and not to allow others to
  31.  * use your version of this file under the terms of the MPL, indicate your
  32.  * decision by deleting the provisions above and replace them with the notice
  33.  * and other provisions required by the GPL or the LGPL. If you do not delete
  34.  * the provisions above, a recipient may use your version of this file under
  35.  * the terms of any one of the MPL, the GPL or the LGPL.
  36.  *
  37.  * ***** END LICENSE BLOCK ***** */
  38.  
  39. /**
  40.  * Constructor of calItipEmailTransport object
  41.  */
  42. function calItipEmailTransport() {
  43.     this.wrappedJSObject = this;
  44.     this._initEmailTransport();
  45. }
  46.  
  47. calItipEmailTransport.prototype = {
  48.  
  49.     QueryInterface: function cietQI(aIid) {
  50.         if (!aIid.equals(Components.interfaces.nsISupports) &&
  51.             !aIid.equals(Components.interfaces.calIItipTransport))
  52.         {
  53.             throw Components.results.NS_ERROR_NO_INTERFACE;
  54.         }
  55.  
  56.         return this;
  57.     },
  58.  
  59.     mHasXpcomMail: false,
  60.     mAccountMgrSvc: null,
  61.     mDefaultAccount: null,
  62.     mDefaultSmtpServer: null,
  63.  
  64.     mDefaultIdentity: null,
  65.     get defaultIdentity() {
  66.         return this.mDefaultIdentity.email;
  67.     },
  68.  
  69.     mSenderAddress: null,
  70.     get senderAddress() {
  71.         return this.mSenderAddress;
  72.     },
  73.     set senderAddress(aValue) {
  74.         return (this.mSenderAddress = aValue);
  75.     },
  76.  
  77.     get type() {
  78.         return "email";
  79.     },
  80.  
  81.     /**
  82.      * Pass the transport an itipItem and have it figure out what to do with
  83.      * it based on the itipItem's methods.
  84.      */
  85.     simpleSendResponse: function cietSSR(aItem) {
  86.         var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].
  87.                   getService(Components.interfaces.nsIStringBundleService);
  88.         var sb = sbs.createBundle("chrome://lightning/locale/lightning.properties");
  89.  
  90.         var itemList = aItem.getItemList({ });
  91.  
  92.         // Get my participation status
  93.         var myPartStat;
  94.         var foundMyself = false;
  95.         var attendee = itemList[0].getAttendeeById("mailto:" +
  96.                                                    this.mDefaultIdentity.email);
  97.         if (attendee) {
  98.             myPartStat = attendee.participationStatus;
  99.             foundMyself = true;
  100.         }
  101.  
  102.         if (!foundMyself) {
  103.             // I didn't find myself in the attendee list.
  104.             //
  105.             // This can happen when invitations are sent to email aliases
  106.             // instead of mDefaultIdentity.email (ex: lilmatt vs. mwillis),
  107.             // or if an invitation is sent to a listserv.
  108.             //
  109.             // We'll need to make more decisions regarding how to handle this
  110.             // in the future. (ex: Prompt? Find myself in list?)  For now, we
  111.             // just don't send a response.
  112.             return;
  113.         }
  114.  
  115.         var name = this.mDefaultIdentity.email;
  116.         if (this.mDefaultIdentity.fullName) {
  117.             name = this.mDefaultIdentity.fullName + " <" + name + ">";
  118.         }
  119.  
  120.         var summary;
  121.         if (itemList[0].getProperty("SUMMARY")) {
  122.             summary = itemList[0].getProperty("SUMMARY");
  123.         } else {
  124.             summary = "";
  125.         }
  126.         var subj = sb.formatStringFromName("itipReplySubject", [summary], 1);
  127.  
  128.         // Generate proper body from my participation status
  129.         var body;
  130.         dump("\n\nthis is partstat: " + myPartStat + "\n");
  131.         if (myPartStat == "DECLINED") {
  132.             body = sb.formatStringFromName("itipReplyBodyDecline",
  133.                                            [name], 1);
  134.         } else {
  135.             body = sb.formatStringFromName("itipReplyBodyAccept",
  136.                                            [name], 1);
  137.         }
  138.  
  139.         var recipients = [itemList[0].organizer];
  140.  
  141.         this.sendItems(recipients.length, recipients, subj, body, aItem);
  142.     },
  143.  
  144.     sendItems: function cietSI(aCount, aRecipients, aSubject, aBody, aItem) {
  145.         LOG("sendItems: Sending Email...");
  146.         if (this.mHasXpcomMail) {
  147.             this._sendXpcomMail(aCount, aRecipients, aSubject, aBody, aItem);
  148.         } else {
  149.             // Sunbird case: Call user's default mailer on system.
  150.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  151.         }
  152.     },
  153.  
  154.     checkForInvitations: function cietCFI(searchStart) {
  155.         // We only need to do trigger a check for incoming invitations if we
  156.         // are not Thunderbird.
  157.         if (!this.mHasXpcomMail) {
  158.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  159.         }
  160.     },
  161.  
  162.     _initEmailTransport: function cietIES() {
  163.         this.mHasXpcomMail = true;
  164.  
  165.         try {
  166.             this.mAccountMgrSvc =
  167.                  Components.classes["@mozilla.org/messenger/account-manager;1"].
  168.                  getService(Components.interfaces.nsIMsgAccountManager);
  169.  
  170.             var smtpSvc = Components.classes["@mozilla.org/messengercompose/smtp;1"].
  171.                           getService(Components.interfaces.nsISmtpService);
  172.             this.mSmtpServer = smtpSvc.defaultServer;
  173.  
  174.             this.mDefaultAccount = this.mAccountMgrSvc.defaultAccount;
  175.             this.mDefaultIdentity = this.mDefaultAccount.defaultIdentity;
  176.  
  177.             if (!this.mDefaultIdentity) {
  178.                 // If there isn't a default identity (i.e Local Folders is your
  179.                 // default identity, then go ahead and use the first available
  180.                 // identity.
  181.                 var allIdentities = this.mAccountMgrSvc.allIdentities;
  182.                 if (allIdentities.Count() > 0) {
  183.                     this.mDefaultIdentity = allIdentities.GetElementAt(0)
  184.                                                          .QueryInterface(Components.interfaces.nsIMsgIdentity);
  185.                 } else {
  186.                     // If there are no identities, then we are in the same
  187.                     // situation as if we didn't have Xpcom Mail.
  188.                     this.mHasXpcomMail = false;
  189.                     LOG("initEmailService: No XPCOM Mail available: " + e);
  190.                 }
  191.             }
  192.         } catch (ex) {
  193.             // Then we must resort to operating system specific means
  194.             this.mHasXpcomMail = false;
  195.         }
  196.     },
  197.  
  198.     _sendXpcomMail: function cietSXM(aCount, aToList, aSubject, aBody, aItem) {
  199.         // Save calItipItem to a temporary file.
  200.         LOG("sendXpcomMail: Creating temp file for attachment.");
  201.         var msgAttachment = Components.classes["@mozilla.org/messengercompose/attachment;1"].
  202.                             createInstance(Components.interfaces.nsIMsgAttachment);
  203.         msgAttachment.url = this._createTempIcsFile(aItem);
  204.         if (!msgAttachment.url) {
  205.             LOG("sendXpcomMail: No writeable path in profile!");
  206.             // XXX Is there an "out of disk space" error?
  207.             throw Components.results.NS_ERROR_FAILURE;
  208.         }
  209.  
  210.         msgAttachment.name =  "calendar.ics";
  211.         msgAttachment.contentType = "text/calendar";
  212.         msgAttachment.contentTypeParam = "method=" + aItem.responseMethod;
  213.         // Destroy the attachment after sending
  214.         msgAttachment.temporary = true;
  215.  
  216.         // compose fields for message
  217.         var composeFields = Components.classes["@mozilla.org/messengercompose/composefields;1"].
  218.                             createInstance(Components.interfaces.nsIMsgCompFields);
  219.         composeFields.useMultipartAlternative = true;
  220.         composeFields.characterSet = "UTF-8";
  221.         // TODO: xxx make this use the currently selected mail account, if
  222.         // possible, and default to the default account if the selection
  223.         // is unclear.
  224.         var toList = "";
  225.         for each (var recipient in aToList) {
  226.             // Strip leading "mailto:" if it exists.
  227.             var rId = recipient.id.replace(/^mailto:/i, "");
  228.  
  229.             // Prevent trailing commas.
  230.             if (toList.length > 0) {
  231.                 toList += ",";
  232.             }
  233.  
  234.             // Add this recipient id to the list.
  235.             toList += rId;
  236.         }
  237.         composeFields.to = toList;
  238.         composeFields.from = this.mDefaultIdentity.email;
  239.         composeFields.replyTo = this.mDefaultIdentity.replyTo;
  240.         composeFields.subject = aSubject;
  241.         composeFields.body = aBody;
  242.         composeFields.addAttachment(msgAttachment);
  243.  
  244.         // Message paramaters
  245.         var composeParams = Components.classes["@mozilla.org/messengercompose/composeparams;1"].
  246.                             createInstance(Components.interfaces.nsIMsgComposeParams);
  247.         composeParams.composeFields = composeFields;
  248.         // TODO: xxx: Make this a pref or read the default pref
  249.         composeParams.format = Components.interfaces.nsIMsgCompFormat.PlainText;
  250.         composeParams.type = Components.interfaces.nsIMsgCompType.New;
  251.  
  252.         var composeService = Components.classes["@mozilla.org/messengercompose;1"].
  253.                              getService(Components.interfaces.nsIMsgComposeService);
  254.         switch (aItem.autoResponse) {
  255.             case (Components.interfaces.calIItipItem.USER):
  256.                 LOG("sendXpcomMail: Found USER autoResponse type.");
  257.  
  258.                 // Open a compose window
  259.                 var url = "chrome://messenger/content/messengercompose/messengercompose.xul"
  260.                 composeService.OpenComposeWindowWithParams(url, composeParams);
  261.                 break;
  262.             case (Components.interfaces.calIItipItem.AUTO):
  263.                 LOG("sendXpcomMail: Found AUTO autoResponse type.");
  264.  
  265.                 var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
  266.                          getService(Components.interfaces.nsIWindowWatcher);
  267.                 var win = ww.activeWindow;
  268.                 var msgCompose = Components.classes["@mozilla.org/messengercompose/compose;1"].
  269.                                  createInstance(Components.interfaces.nsIMsgCompose);
  270.                 msgCompose.Initialize(win, composeParams);
  271.                 // Fourth param is message window, fifth param is progress.
  272.                 // TODO: xxx decide on whether or not we want progress window
  273.                 msgCompose.SendMsg(Components.interfaces.nsIMsgCompDeliverMode.Now,
  274.                                    this.mDefaultIdentity,
  275.                                    this.mDefaultAccount.key,
  276.                                    null,
  277.                                    null);
  278.                 break;
  279.             case (Components.interfaces.calIItipItem.NONE):
  280.                 LOG("sendXpcomMail: Found NONE autoResponse type.");
  281.  
  282.                 // No response
  283.                 break;
  284.             default:
  285.                 // Unknown autoResponse type
  286.                 throw new Error("sendXpcomMail: " +
  287.                                 "Unknown autoResponse type: " +
  288.                                 aItem.autoResponse);
  289.         }
  290.     },
  291.  
  292.     _createTempIcsFile: function cietCTIF(aItem) {
  293.         var path;
  294.         var itemList = aItem.getItemList({ });
  295.         // This is a workaround until bug 353369 is fixed.
  296.         // Without it, we cannot roundtrip the METHOD property, so we must
  297.         // re-add it to the ICS data as we serialize it.
  298.         //
  299.         // Look at the implicit assumption in the code at:
  300.         // http://lxr.mozilla.org/seamonkey/source/calendar/base/src/calEvent.js#162
  301.         // and it's easy to see why.
  302.         itemList[0].setProperty("METHOD", aItem.responseMethod);
  303.         var calText = "";
  304.         for (var i = 0; i < itemList.length; i++) {
  305.             calText += itemList[i].icalString;
  306.         }
  307.  
  308.         LOG("ICS to be emailed: " + calText);
  309.  
  310.         try {
  311.             var dirUtils = Components.classes["@mozilla.org/file/directory_service;1"].
  312.                            createInstance(Components.interfaces.nsIProperties);
  313.             var tempFile = dirUtils.get("TmpD", Components.interfaces.nsIFile);
  314.             tempFile.append("itipTemp");
  315.             tempFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
  316.  
  317.             var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
  318.                                createInstance(Components.interfaces.nsIFileOutputStream);
  319.             var utf8CalText = this._convertFromUnicode("UTF-8", calText);
  320.  
  321.             // Let's write the file - constants from file-utils.js
  322.             const MODE_WRONLY   = 0x02;
  323.             const MODE_CREATE   = 0x08;
  324.             const MODE_TRUNCATE = 0x20;
  325.             outputStream.init(tempFile,
  326.                               MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE,
  327.                               0600, 0);
  328.             outputStream.write(utf8CalText, utf8CalText.length);
  329.             outputStream.close();
  330.  
  331.             var ioService = Components.classes["@mozilla.org/network/io-service;1"].
  332.                             getService(Components.interfaces.nsIIOService);
  333.             path = ioService.newFileURI(tempFile).spec;
  334.         } catch (ex) {
  335.             LOG("createTempItipFile failed! " + ex);
  336.             path = null;
  337.         }
  338.         LOG("createTempItipFile path: " + path);
  339.         return path;
  340.     },
  341.  
  342.     _convertFromUnicode: function cietCFU(aCharset, aSrc) {
  343.         var unicodeConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
  344.                                createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
  345.         unicodeConverter.charset = aCharset;
  346.         return unicodeConverter.ConvertFromUnicode(aSrc);
  347.     }
  348. };
  349.  
  350. // nsIFactory
  351. const calItipEmailTransportFactory = {
  352.     createInstance: function (outer, iid) {
  353.         if (outer != null)
  354.             throw Components.results.NS_ERROR_NO_AGGREGATION;
  355.         return (new calItipEmailTransport()).QueryInterface(iid);
  356.     }
  357. };
  358.  
  359. /****
  360.  **** module registration
  361.  ****/
  362.  
  363. var calItipEmailTransportModule = {
  364.  
  365.     mCID: Components.ID("{d4d7b59e-c9e0-4a7a-b5e8-5958f85515f0}"),
  366.     mContractID: "@mozilla.org/calendar/itip-transport;1?type=email",
  367.  
  368.     mUtilsLoaded: false,
  369.     loadUtils: function itipEmailLoadUtils() {
  370.         if (this.mUtilsLoaded)
  371.             return;
  372.  
  373.         const jssslContractID = "@mozilla.org/moz/jssubscript-loader;1";
  374.         const jssslIID = Components.interfaces.mozIJSSubScriptLoader;
  375.  
  376.         const iosvcContractID = "@mozilla.org/network/io-service;1";
  377.         const iosvcIID = Components.interfaces.nsIIOService;
  378.  
  379.         var loader = Components.classes[jssslContractID].getService(jssslIID);
  380.         var iosvc = Components.classes[iosvcContractID].getService(iosvcIID);
  381.  
  382.         // Note that unintuitively, __LOCATION__.parent == .
  383.         // We expect to find utils in ./../js
  384.         var appdir = __LOCATION__.parent.parent;
  385.         appdir.append("js");
  386.         var scriptName = "calUtils.js";
  387.  
  388.         var f = appdir.clone();
  389.         f.append(scriptName);
  390.  
  391.         try {
  392.             var fileurl = iosvc.newFileURI(f);
  393.             loader.loadSubScript(fileurl.spec, this.__parent__.__parent__);
  394.         } catch (e) {
  395.             dump("Error while loading " + fileurl.spec + "\n");
  396.             throw e;
  397.         }
  398.  
  399.         this.mUtilsLoaded = true;
  400.     },
  401.     
  402.     registerSelf: function (compMgr, fileSpec, location, type) {
  403.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  404.         compMgr.registerFactoryLocation(this.mCID,
  405.                                         "Calendar iTIP Email Transport",
  406.                                         this.mContractID,
  407.                                         fileSpec,
  408.                                         location,
  409.                                         type);
  410.     },
  411.  
  412.     getClassObject: function (compMgr, cid, iid) {
  413.         if (!cid.equals(this.mCID))
  414.             throw Components.results.NS_ERROR_NO_INTERFACE;
  415.  
  416.         if (!iid.equals(Components.interfaces.nsIFactory))
  417.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  418.  
  419.         this.loadUtils();
  420.  
  421.         return calItipEmailTransportFactory;
  422.     },
  423.  
  424.     canUnload: function(compMgr) {
  425.         return true;
  426.     }
  427. };
  428.  
  429. function NSGetModule(compMgr, fileSpec) {
  430.     return calItipEmailTransportModule;
  431. }
  432.  
  433. function LOG(aString) {
  434.     if (!getPrefSafe("calendar.itip.email.log", false)) {
  435.         return;
  436.     }
  437.     var consoleService = Components.classes["@mozilla.org/consoleservice;1"].
  438.                          getService(Components.interfaces.nsIConsoleService);
  439.     consoleService.logStringMessage(aString);
  440.     dump(aString + "\n");
  441. }
  442.